#ifndef EVM_MEMORY_H
#define EVM_MEMORY_H

#include <stdint.h>

//******************************************************************************
//   TYPEDEFS
//******************************************************************************

typedef struct {
    uint32_t    read  : 1;
    uint32_t    write : 1;
    uint32_t    exec  : 1;

    uint32_t    reserved : 29;
} evm_mem_desc;


typedef struct evm_memchunk {
    uint8_t             *data;
    uint32_t             size;
    evm_mem_desc         desc;
    struct evm_memchunk *next;
} evm_memchunk;


typedef struct {
    uint8_t       **ptrs;
    evm_mem_desc   *types;

    uint32_t        count;
    uint32_t        allocated;
} evm_memindex;


typedef struct evm_memory {
    evm_memchunk *chunks;
    evm_memindex  index;

    uint32_t      allocated;
    uint32_t      used;
    uint32_t      free;
} evm_memory;



//******************************************************************************
//   INTERFACE
//******************************************************************************

uint32_t evm_mem_initialize ( evm_memory **mem );
uint32_t evm_mem_add_chunk  ( evm_memory *mem );
uint32_t evm_mem_optimize   ( evm_memory *mem, uint8_t *wasSomethingOptimized );

uint32_t evm_mem_total_size ( evm_memory *mem );
uint32_t evm_mem_total_used ( evm_memory *mem );
uint32_t evm_mem_total_free ( evm_memory *mem );

uint32_t evm_mem_uint8_at   ( evm_memory *mem, uint32_t ptr, uint8_t  *data );
uint32_t evm_mem_uint32_at  ( evm_memory *mem, uint32_t ptr, uint32_t *data );

uint32_t evm_mem_alloc      ( evm_memory *mem, uint32_t  size );
uint32_t evm_mem_free       ( evm_memory *mem, void     *ptr  );


uint32_t evm_mem_write      ( evm_memory *mem, uint32_t addr, uint8_t *ptr, uint32_t size );


#endif // EVM_MEMORY_H
